﻿package ua.mihaylenko.canvas.utils
{
	import fl.transitions.Tween;
	import fl.transitions.easing.Strong;
	import fl.transitions.TweenEvent;
    import flash.display.DisplayObject;
    import flash.display.InteractiveObject;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.filters.DropShadowFilter;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.utils.Timer;
	import flash.text.TextFormat;
	import ua.mihaylenko.canvas.data.DataManager;
	import ua.mihaylenko.canvas.common.DocumentClass;

    public class PopUpManager extends Sprite
    {
        //======================================================================
        //                            Constant
        //======================================================================            
        private const HORIZONTAL_PADDING:Number = 4;
        private const VERTICAL_PADDING:Number = 1;
        
        private const WIDTH:Number = 136;
        private const HEIGHT:Number = 22;
        private const ELLIPSE_SIZE:Number = 18;
        private const CORNER_RADIUS:Number = ELLIPSE_SIZE / 2;
        
        public const LINE_COLOR:Number = 0xF2F2F2;
        public const FILL_COLOR:Number = 0xE5E5E5;
        
        private const TEXT_SIZE:Number = 10;
        private const TEXT_COLOR:Number = 0x333333;
        
        private const BACKGROUND_FILL_COLOR:Number = 0xCCCCCC;
        private const BACKGROUND_LINE_COLOR:Number = 0x6AACEE;
        
        private const MOUSE_X_OFFSET:Number = 15;
        private const MOUSE_Y_OFFSET:Number = 10;
        
        private const FADE_DURATION:Number = 0.01;
        private const DELAY_DURATION:uint = 50;
        
        private const DROP_SHADOW_ALPHA:Number = 0.3;
        private const SWFWIDTH:uint = 552;
		private const SWFHEIGHT:uint = 402;
        
        //======================================================================
        //                            Variables
        //======================================================================        
        private var _background:Sprite;
        
        private var _text:String;
        private var _textField:TextField;

        private var _hoverObject:InteractiveObject;    
        private var _delayTimer:Timer;
        
        private var onHidePopUp:Tween;
		private var onShowPopUp:Tween;
        //======================================================================
        //                            Constructor
        //======================================================================        
        /**
         * 
         * constructor
         * pull out the text from arguments, initiallize
         * 
         * */
        public function PopUpManager(text:String = "")
        {
            _text = text;
            init();
        }        
        
        //======================================================================
        //                            Private Methods
        //======================================================================        
        
        /**
         * 
         * instantiate all necessary elements
         * set any other default values (tool tip should not be mouse enabled)
         * 
         * */
        private function init():void
        {
            createTimer();
            createChildren();
                                    
            this.alpha = 0;
            this.mouseEnabled = false;
            this.mouseChildren = false
        }
        
        /**
         * 
         * instantiate the timer for delaying tool tip visiblity
         * 
         * */
        private function createTimer():void
        {
            _delayTimer = new Timer(DELAY_DURATION, 1);
            _delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onDelayComplete, false, 0, true);
        }
        
        /**
         * 
         * create the background image and text, then add to stage in the correct order
         * 
         * */
        private function createChildren():void
        {
            //trace("%%%%%%%%%% Creating Children");
            createTextField();
            createBackground();
            
            addChild(_background);
            addChild(_textField);
        }
        
        /**
         * 
         * setup the text field with given text
         * 
         * */
        private function createTextField():void
        {
            _textField = new TextField();
            //TextUtil.setTextInToyota(_textField, "", FontLib.Verdana.fontName, 10, TEXT_COLOR);
			
			var tmpTextFormat:TextFormat = new TextFormat("Arial", 10, TEXT_COLOR);
            
			_textField.defaultTextFormat = tmpTextFormat;
			//_textField.selectable = false;
			//textField.embedFonts = true;
			//textField.antiAliasType = AntiAliasType.ADVANCED;
			
            _textField.autoSize = TextFieldAutoSize.LEFT;
            
            _textField.x = HORIZONTAL_PADDING;
            _textField.y = VERTICAL_PADDING;            
            setTextField();
        }
        
        /**
         * 
         * sets the text to the textfield
         * 
         * */
        private function setTextField():void
        {
            _textField.text = _text;            
        }
        
        /**
         * 
         * create the background image for the text to sit on top of
         * 
         * */
        private function createBackground():void
        {
            var m:Matrix = new Matrix();
            m.createGradientBox(WIDTH - 2, HEIGHT - 2, Math.PI / 2);
            
            _background = new Sprite();
            _background.x = 1;        

            _background.graphics.lineStyle(1, BACKGROUND_LINE_COLOR, 1);
			if (DataManager.getInatsnce().bgPopUpColor) {
				_background.graphics.beginFill(DataManager.getInatsnce().bgPopUpColor, 1);
			}else{
				_background.graphics.beginFill(BACKGROUND_FILL_COLOR, 1);
			}
            _background.graphics.drawRect(0, 0, WIDTH - 2, HEIGHT - 2);
            _background.graphics.endFill();
            
            _background.scale9Grid = new Rectangle(CORNER_RADIUS, CORNER_RADIUS, WIDTH - ELLIPSE_SIZE, HEIGHT - ELLIPSE_SIZE);
            
            _background.filters = new Array(new DropShadowFilter(4, 45, 0, DROP_SHADOW_ALPHA));
            
            setBackgroundSize();
        }
        
        /**
         * 
         * size the background image to the text field dimensions and add padding
         * 
         * */
        private function setBackgroundSize():void
        {
            _background.height = _textField.height + (VERTICAL_PADDING);
            _background.width = _textField.width + (HORIZONTAL_PADDING * 2);
        }
        

        /**
         * 
         * as long as the text provided isn't blank, reset and start the delay timer, and add a mouse move
         * event to the hover object
         * 
         * */
        private function addArticleToolTip(e:MouseEvent):void
        {
            showArticleToolTip();
        }
        
        
        /**
         * 
         * when the delay is done, add the tool tip to the stage and fade it in
         * 
         * */
        private function onDelayComplete(e:TimerEvent):void
        {
			DocumentClass.AppStage.addChild(this);			
			if (onHidePopUp) {
				onHidePopUp.stop();
				onHidePopUp.removeEventListener(TweenEvent.MOTION_FINISH, closePopUp);
				onHidePopUp = null;
			}
			this.visible = true;
            //Tweener.addTween(this, { alpha:1, time:FADE_DURATION, transition:"easeIn" } );
			onShowPopUp = new Tween(this, "alpha", Strong.easeIn, 0, 1, FADE_DURATION, true);
        }
        
        /**
         * 
         * sync the tool tip x/y to the mouse x/y and offset
         * 
         * */
        private function syncArticleToolTipPosition(e:Event):void
        {
            this.x = DocumentClass.AppStage.mouseX + MOUSE_X_OFFSET;
            this.y = DocumentClass.AppStage.mouseY + MOUSE_Y_OFFSET;
            
            
            if(this.x + this.width >= SWFWIDTH)
            {
				this.x = DocumentClass.AppStage.mouseX - this.width;              
            }
			
			if (this.y + this.height >= SWFHEIGHT)
			{
				this.y = DocumentClass.AppStage.mouseY - this.height;
			}
        }
        
        /**
         * 
         * hide the tool tip on roll out
         * 
         * */
        private function removeArticleToolTip(e:MouseEvent):void
        {
            hideArticleToolTip();
        }
        
    
        /**
         * 
         * after tool tip is faded out, remove it from the stage
         * 
         * */
        private function removeArticleToolTipFromStage():void
        {
            if (DocumentClass.AppStage.contains(this))
                DocumentClass.AppStage.removeChild(this);
        }
        
    
        //======================================================================
        //                            Public Methods
        //======================================================================    
        
        
        public function showArticleToolTip():void
        {
            if (this.text != "")
            {            
                //Tweener.removeTweens(this);
				if (onHidePopUp) {
					onHidePopUp.stop();
					onHidePopUp.removeEventListener(TweenEvent.MOTION_FINISH, closePopUp);
					onHidePopUp = null;
				}
				this.visible = true;
                this.alpha = 0;
                
                _delayTimer.reset();
                _delayTimer.start();
                
                this.addEventListener(Event.ENTER_FRAME, syncArticleToolTipPosition, false, 0, true);
            }
        }
                
        /**
         * 
         * remove the mouse move listener from the hover object and fade out the tool tip
         * when fade out is complete, removeArticleToolTipFromStage() is called 
         * 
         * */
        public function hideArticleToolTip():void
        {
            _delayTimer.stop();
            
            this.removeEventListener(Event.ENTER_FRAME, syncArticleToolTipPosition);
            if (onShowPopUp) {
				onShowPopUp.stop();
				onShowPopUp = null;
			}
            //Tweener.removeTweens(this);
            //Tweener.addTween(this, { alpha:0, time:FADE_DURATION, transition:"easeIn" } );
			onHidePopUp = new Tween(this, "alpha", Strong.easeIn, 1, 0, FADE_DURATION, true);
			onHidePopUp.addEventListener(TweenEvent.MOTION_FINISH, closePopUp);
			
        }     
		private function closePopUp(event:TweenEvent) {
			onHidePopUp.removeEventListener(TweenEvent.MOTION_FINISH, closePopUp);
			this.visible = false;
			onHidePopUp = null;
		}
        /**
         * 
         * set the text value, which then is set on the text field. background image needs
         * to be resized at this point. hide the tool tip the text is blank
         * 
         * */
        public function set text(value:String):void
        {
            _text = value;
            
            if (value == "")
            {
                hideArticleToolTip();
            }
            else
            {
                setTextField();
                setBackgroundSize();
            }
        }
        
        /**
         * 
         * attach this tool tip to an interactive object by adding roll over and roll out 
         * listeners to said object
         * 
         * */
        public function attach(hoverObject:InteractiveObject):void
        {
            /** just in case you've already attached this tool tip to this object **/
            detach();
            _hoverObject = hoverObject;
            
            hoverObject.addEventListener(MouseEvent.ROLL_OVER, addArticleToolTip, false, 0, true);
            hoverObject.addEventListener(MouseEvent.ROLL_OUT, removeArticleToolTip, false, 0, true);
			//hoverObject.addEventListener(MouseEvent.MOUSE_DOWN, removeArticleToolTip, false, 0, true);
        }        
        
        /**
         * 
         * detach this tool tip from an interactive object by removing roll over and roll out 
         * listeners to said object
         * 
         * */
        public function detach():void
        {
            if (_hoverObject)
            {
                _hoverObject.removeEventListener(MouseEvent.ROLL_OVER, addArticleToolTip);                    
                _hoverObject.removeEventListener(MouseEvent.ROLL_OUT, removeArticleToolTip);
            }
            
        }
            
        public function get text():String { return _text; }    
        
        public function set delay(value:Number):void { _delayTimer.delay = value; }
        public function get delay():Number { return _delayTimer.delay; }
        
        public function dispose():void
        {
            while(this.numChildren > 0)
            {
                var child:DisplayObject = this.getChildAt(0);
                this.removeChild(child);
                child = null;
            }
        }        
    }
	
}